package com.hengpeng.itfin.tools;

import java.math.BigDecimal;

import com.hengpeng.itfinbase.en.DurationType;

public class InvestUtils
{
	/**
	 * <pre>
	 * 精度转换(四舍六入5成双)
	 * </pre>
	 * @param monthMoney 单位：分
	 * @return
	 */
	public static long accuracy(double monthMoney)
	{
		BigDecimal dec = new BigDecimal(monthMoney);
		BigDecimal setScale = dec.setScale(0, BigDecimal.ROUND_HALF_EVEN);
		return setScale.longValue();
	}

	/**
	 * <pre>
	 * 等额本息还款（每月月供额=〔贷款本金×月利率×(1＋月利率)＾还款月数〕÷〔(1＋月利率)＾还款月数-1〕）
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static long equalInterest(Long money, Double rate, int duration)
	{
	    BigDecimal moneyDecimal=new BigDecimal(money);
	    BigDecimal rateDecimal=new BigDecimal(rate);
		BigDecimal monthRate = rateDecimal.divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP);// / (12 * 100);// 月利率
		BigDecimal rates = new BigDecimal(1);// (1＋月利率)＾还款月数
		for (int i = 0; i < duration; i++)
		{
			rates = rates.multiply(new BigDecimal(1).add(monthRate));
		}
		BigDecimal multiply = moneyDecimal.multiply(monthRate).multiply(rates);
		BigDecimal subtract = rates.subtract(new BigDecimal(1));
		BigDecimal month = multiply.divide(subtract,99,BigDecimal.ROUND_HALF_UP);
		return accuracy(month.doubleValue());// 每月还款额
	}

	/**
	 * <pre>
	 * 等额本金还款总额（还款总额=(还款月数+1)*贷款额*月利率/2+贷款额）
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static long equalPrincipal(Long money, Double rate, int duration)
	{
	    BigDecimal moneyDecimal=new BigDecimal(money);
        BigDecimal rateDecimal=new BigDecimal(rate);
        BigDecimal durationDecimal=new BigDecimal(duration);
		BigDecimal monthRate =rateDecimal.divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP);// rate / (12 * 100);// 月利率
		BigDecimal total = (durationDecimal.add(new BigDecimal(1))).multiply(moneyDecimal).multiply(monthRate).divide(new BigDecimal(2),99,BigDecimal.ROUND_HALF_UP).add(moneyDecimal);
		return accuracy(total.doubleValue());
	}

	/**
	 * <pre>
	 * 一次性还本付息的利息与按月付息到期还本总利息计算方式相同
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static long rtcapitalInterest(Long money, Double rate, int duration, DurationType type)
	{
		long rtMoney = 0;
		BigDecimal moneyDecimal=new BigDecimal(money);
		BigDecimal rateDecimal=new BigDecimal(rate);
		BigDecimal durationDecimal=new BigDecimal(duration);
		switch (type)
		{
			case MONTH:
				rtMoney = accuracy(moneyDecimal.multiply(rateDecimal).multiply(durationDecimal).divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP).doubleValue());//; * rate * duration / (100 * 12));
				break;
			case DAY:
				rtMoney = accuracy(moneyDecimal.multiply(rateDecimal).multiply(durationDecimal).divide(new BigDecimal(36500),99,BigDecimal.ROUND_HALF_UP).doubleValue());//; * rate * duration / (100 * 12));//accuracy(money * rate * duration / (100 * 365));
				break;
		}
		return rtMoney;
	}

	/**
	 * <pre>
	 * 按月付息每个月的利息
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static long rtcapitalMonthInterest(Long money, Double rate, DurationType type)
	{
		long rtMoney = 0;
		BigDecimal moneyDecimal=new BigDecimal(money);
        BigDecimal rateDecimal=new BigDecimal(rate);
		switch (type)
		{
			case MONTH:
				rtMoney = accuracy(moneyDecimal.multiply(rateDecimal).divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP).doubleValue());// * rate / (100 * 12));
				break;
			case DAY:
				rtMoney = accuracy(moneyDecimal.multiply(rateDecimal).divide(new BigDecimal(36500),99,BigDecimal.ROUND_HALF_UP).doubleValue());//money * rate / (100 * 365));
				break;
		}
		return rtMoney;
	}

	/**
	 * <pre>
	 * 等额本息还款每月应还本金金额
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static Long[] equalInterestMonthBase(Long money, Double rate, int duration)
	{
	    BigDecimal rateDecimal=new BigDecimal(rate);
		BigDecimal monthRate = rateDecimal.divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP);//rate / (12 * 100);// 月利率
		BigDecimal monthMoney = new BigDecimal(equalInterest(money, rate, duration));// 每月还款额
		BigDecimal[] allMonths = new BigDecimal[duration + 1];// 每月剩余本金
		BigDecimal base = new BigDecimal(money);
		for (int i = 0; i <= duration; i++)
		{
			allMonths[i] = base;
			base = new BigDecimal(accuracy(base.multiply(monthRate.add(new BigDecimal(1))).subtract(monthMoney).doubleValue()));
		}
		BigDecimal[] monthes = new BigDecimal[duration];// 每月应还本金
		BigDecimal totalMoney = new BigDecimal(0);
		for (int i = 1; i <= monthes.length; i++)
		{
			monthes[i - 1] = allMonths[i - 1].subtract(allMonths[i]);
			totalMoney = totalMoney.add(monthes[i - 1]);
		}
		monthes[0] = monthes[0].add(new BigDecimal(money)).subtract(totalMoney);
		Long[] months=new Long[monthes.length];
		for(int i=0;i<monthes.length;i++){
		    months[i]=monthes[i].longValue();
		}
		return months;
	}

	/**
	 * <pre>
	 * 等额本金,每月应还利息
	 * </pre>
	 * @param money 金额
	 * @param rate 利率(百分数)
	 * @param duration 时长，月数
	 */
	public static Long[] equalPrincipalMonthInterest(Long money, Double rate, int duration)
	{
		BigDecimal monthRate = new BigDecimal(rate).divide(new BigDecimal(1200),99,BigDecimal.ROUND_HALF_UP);// rate / (12 * 100);// 月利率
		BigDecimal monthBase = new BigDecimal(accuracy(new BigDecimal(money).divide(new BigDecimal(duration),99,BigDecimal.ROUND_HALF_UP).doubleValue()));// 每月应还本金
		BigDecimal monthLoss = new BigDecimal(money);// 每月剩余本金
		BigDecimal[] interests = new BigDecimal[duration];
		for (int i = 0; i < duration; i++)
		{
			interests[i] = new BigDecimal(accuracy(monthLoss.multiply(monthRate).doubleValue()));
			monthLoss = monthLoss.subtract(monthBase);
		}
		Long[] interest=new Long[interests.length];
		for(int i=0;i<interests.length;i++){
		    interest[i]=interests[i].longValue();
		}
		return interest;
	}

	public static void main(String[] args)
	{
        Long[] base = equalPrincipalMonthInterest(1100L, 11.00, 12);
        for(int i=0;i<base.length;i++){
            System.out.println(base[i]);
        }
    }
}
